package fr.synthese.gutemberg;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
//import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;



/**
 * @author devref101
 * classe métier.
 *
 */
public class Traitement {


	/**
	 * @param 
	 * paramètres statiques
	 */
	private static List<Mot> listGutemberg; // Liste de tous les mots
	private static List<Mot> listFinParVer; // Liste des mots se terminant par "ver"
	
	private static Map<String, List<Mot>> mapOne; //contient des listes de mots selon un type de liste
	private static Map<String, List<Mot>> mapTwo; //contient des listes de mots selon le premier caractère des mots
	private static Map<String, List<Mot>> mapThree; //contient des listes de mots selon le nombre de caractères des mots
	private static Map<String, List<Mot>> mapTriee; //contient des listes de mots triée par la clé
	
	private static String titre;
	private static int nbLignes = 20000; // param. lecture écriture 
										//d'un nombre limité de lignes

	/**
	 * getteurs & setters
	 */



	public Map<String, List<Mot>> getMapOne() {
		return mapOne;
	}

	public void setMapOne(Map<String, List<Mot>> mapOne) {
		Traitement.mapOne = mapOne;
	}

	public Map<String, List<Mot>> getMapTwo() {
		return mapTwo;
	}

	public void setMapTwo(Map<String, List<Mot>> mapTwo) {
		Traitement.mapTwo = mapTwo;
	}

	public Map<String, List<Mot>> getMapThree() {
		return mapThree;
	}

	public void setMapThree(Map<String, List<Mot>> mapThree) {
		Traitement.mapThree = mapThree;
	}

	public Map<String, List<Mot>> getMapTriee() {
		return mapTriee;
	}

	public void setMapTriee(Map<String, List<Mot>> mapTriee) {
		Traitement.mapTriee = mapTriee;
	}

	/**
	 * @param  
	 * Méthode ecritCollection : écrit une collection dans un fichier.
	 * Paramètres : pCollection : nom du fichier à écrire
	 *   	        pMap         : collection (Map) de mots à décrire dans le fichier 
	 *   			Description de la colection : nombre de mots par clé de la collection
	 */
	public final void ecritCollection(String pCollection, Map pMap) {
		Map<String, List<Mot>> mapTriee = new TreeMap<String, List<Mot>>(pMap);
		System.out.println("========================================================================================");
		System.out.println("Ecriture de la collection " + pCollection + " qui comprend " + mapTriee.size() + " élément(s)");
		System.out.println("========================================================================================");
	    Iterator<String> it = mapTriee.keySet().iterator();
		OutputStream outputStream= null ;
		try {
			outputStream = new FileOutputStream(pCollection+".txt");
			Writer writer = new OutputStreamWriter(outputStream);
			//writer.write("toto");
			// on prépare OutputStreamWriter => on remplira un Writer 
			// qui sera écrit dans le flux outputStream
			String Newligne=System.getProperty("line.separator"); 
			//while ((line = bfr.readLine()) != null && i !=30) {
			while (it.hasNext()) {
		    	String item = it.next();
		    	//System.out.println("collection : " + pCollection);
				if (pCollection == "motsParNbLettres") {
					String lineLn="Nombre de mots contenant " + item + " lettres : " + mapTriee.get(item).size() + Newligne; 
					writer.write(lineLn);
				} else {
					String lineLn="Nombre de mots commençant par " + item + " : " + mapTriee.get(item).size() + Newligne; 
					writer.write(lineLn);
				}
			}
			writer.close();
		} catch (IOException e) {
			System.err.println("pb ecriture fichier");
			e.printStackTrace();
		}
	
		System.out.println("Le fichier " + pCollection + " est écrit !!!") ;
	}
	
	public final void motsParTailles() {
		System.out.println("===================================================================================");
		System.out.println("Voici la liste des mots par taille non triée ...");
		System.out.println("===================================================================================");
		Map<String, List<Mot>> mapTriee = new TreeMap<String, List<Mot>>(mapThree);
		Iterator<String> it = mapThree.keySet().iterator();
	    while(it.hasNext()) {
	    	String nbCar = it.next();
	    	System.out.println("Nombre de mots contenant " + nbCar + " lettres : " + mapThree.get(nbCar).size() );	
	    }
		System.out.println("===================================================================================");
		System.out.println("Voici la liste des mots par taille triée ...");
		System.out.println("===================================================================================");
		Iterator<String> it2 = mapTriee.keySet().iterator();
	    while(it2.hasNext()) {
	    	String nbCar = it2.next();
	    	System.out.println("Nombre de mots contenant " + nbCar + " lettres : " + mapTriee.get(nbCar).size() );	
	    }
		
	}
	
	public final void tailleParFirstCar() {
		System.out.println("===================================================================================");
		System.out.println("Voici la liste des mots par leur premier caractère non triée ...");
		System.out.println("===================================================================================");
	    Iterator<String> it = mapTwo.keySet().iterator();
	    while(it.hasNext()) {
	    	String carUn = it.next();
	    	System.out.println("Nombre de mots commençant par " + carUn + " : " + mapTwo.get(carUn).size() );	
	    }
		System.out.println("===================================================================================");
		System.out.println("Voici la liste des mots par leur premier caractère triée ...");
		System.out.println("===================================================================================");
		Map<String, List<Mot>> mapTriee = new TreeMap<String, List<Mot>>(mapTwo);
	    Iterator<String> it2 = mapTriee.keySet().iterator();
	    while(it2.hasNext()) {
	    	String carUn = it2.next();
	    	System.out.println("Nombre de mots commençant par " + carUn + " : " + mapTriee.get(carUn).size() );	
	    }
		
	}
	
	public final void montreListe(String ptypList) {
		List<Mot> laListe = this.mapOne.get(ptypList);
		System.out.println("===================================================================================");
		System.out.println("Voici la liste des mots " + ptypList + " qui comprend " + laListe.size() + " mot(s)");
		System.out.println("===================================================================================");
	    Iterator<Mot> it = laListe.iterator();
	    while(it.hasNext())
	      System.out.println(it.next());	
	    }
	
	public final void ecritListe(String ptypList) {
		List<Mot> laListe = this.mapOne.get(ptypList);
		System.out.println("========================================================================================");
		System.out.println("Ecriture de la liste de mots " + ptypList + " qui comprend " + laListe.size() + " mot(s)");
		System.out.println("========================================================================================");
	    Iterator<Mot> it = laListe.iterator();
		OutputStream outputStream= null ;
		try {
			outputStream = new FileOutputStream(ptypList+".txt");
			Writer writer = new OutputStreamWriter(outputStream);
			//writer.write("toto");
			// on prépare OutputStreamWriter => on remplira un Writer 
			// qui sera écrit dans le flux outputStream
			String Newligne=System.getProperty("line.separator"); 
			//while ((line = bfr.readLine()) != null && i !=30) {
			while (it.hasNext()) {
				String lineLn=it.next().getNomMot()+Newligne; 
				writer.write(lineLn);
			}
			writer.close();
		} catch (IOException e) {
			System.err.println("pb ecriture fichier");
			e.printStackTrace();
		}
	
		System.out.println("Le fichier " + ptypList + " est écrit !!!") ;
	}
	
	public final void ecritureFichier(final String url) {

		System.out.println("Le fichier " + titre + " va être écrit après un retour clavier..") ;
		Scanner sc =new Scanner(System.in); 

		String type = sc.nextLine(); // Attendre  retour clavier
		
		/**
		 * Les lignes du fichiers récupérées.
		 */
		String line = null;

		// on traite le fichier
		URL u;
		OutputStream outputStream = null ;
		try {
			outputStream = new FileOutputStream(titre+".txt");
		} catch (FileNotFoundException e1) {
			System.err.println("pb ecriture fichier");
			e1.printStackTrace();
		}


		
		try {
			u = new URL(url);
			// vérification possibilité lecture
			try {
				u.openStream().read();
			} catch (Exception e) {
				System.err.println("LE FICHIER EST ILLISIBLE !");
				e.printStackTrace();
			}
			// on stocke le flux d'octets dans InputStreamReader
			InputStreamReader ipsr = new InputStreamReader(u.openStream()); 
			// on récupère InputStreamReader => dans un BufferedReader
			BufferedReader bfr = new BufferedReader(ipsr);
			// on prépare OutputStreamWriter => on remplira un Writer 
			// qui sera écrit dans le flux outputStream
			Writer       writer       = new OutputStreamWriter(outputStream);
			// StringBuffer buffer = new StringBuffer(); 
			// instancié ma liste !

			int i = 0;
			//titre = "sans titre";
			String Newligne=System.getProperty("line.separator"); 
			//while ((line = bfr.readLine()) != null && i !=nbLignes) {
			while ((line = bfr.readLine()) != null) {
				String lineLn=line+Newligne; 
				writer.write(lineLn);
				i++ ;
			}
			

		bfr.close();  		// buffer lecture
		writer.close();		// buffer écriture

	} catch (MalformedURLException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	System.out.println("Le fichier " + titre + " est écrit !!!") ;
}

	public final List<Mot> recuperationFichier(final String url) {

		/**
		 * Les lignes du fichiers récupérées.
		 */
		String line = null;

		listGutemberg = new ArrayList<>();
		listFinParVer = new ArrayList<>();
		
		mapOne = new HashMap<String, List<Mot>>();
		mapTwo = new HashMap<String, List<Mot>>();
		mapThree = new HashMap<String, List<Mot>>();
		
		//Object o = mapOne.get("m-a").add(mot);
		// on traite le fichier
		URL u;
		try {
			u = new URL(url);
			// vérification possibilité lecture
			try {
				u.openStream().read();
			} catch (Exception e) {
				System.err.println("LE FICHIER EST ILLISIBLE !");
				e.printStackTrace();
			}
			// on stocke le flux d'octets dans InputStreamReader
			InputStreamReader ipsr = new InputStreamReader(u.openStream()); 
			// on récupère InputStreamReader => dans un BufferedReader
			BufferedReader bfr = new BufferedReader(ipsr);

			// StringBuffer buffer = new StringBuffer(); 
			// instancié ma liste !

			listGutemberg = new ArrayList<>();
			
			// quel est le contenu de H1 ?
			// trouverTitre(line);
			// ou est le début ?
			boolean trouve = false;
			int i = 0;
			titre = "sans titre";
			//while ((line = bfr.readLine()) != null && i !=nbLignes) {
			while ((line = bfr.readLine()) != null) {

				trouve = trouverTitre(line);
				if (trouve) { 
					//titre = line.substring(0, line.length()); 
					titre = line.split(">")[1];
					titre = titre.split("</")[0];
					titre = titre.trim();
					titre = titre.replace(" ", "-");
					System.out.println("le titre est : " + titre);
					}
				
				if (!line.contains("<") && !line.equals("")) {
				
				line = line.replace(" ", ""); // on retire les espaces éventuels,
												//en particulier en début de ligne
				
				Mot mot = new Mot(line);
				int tailleMot = mot.getNbCaracMot();
				//System.out.println("taille : " + String.valueOf(tailleMot));
				String sTaille = String.valueOf(tailleMot);
				if (sTaille.length() < 2) {sTaille = "0" + sTaille ;}
				if(!mapThree.containsKey(sTaille)) {
					List<Mot> listevide = null;
					listevide = new ArrayList<>();
					mapThree.put(sTaille, listevide);
				}
				mapThree.get(sTaille).add(mot);
				
				char firstCar = mot.getCarUn();
				if(!mapTwo.containsKey(Character.toString(firstCar))) {
					List<Mot> listevide = null;
					listevide = new ArrayList<>();
					mapTwo.put(Character.toString(firstCar), listevide);
				}
				mapTwo.get(Character.toString(firstCar)).add(mot);
				
				//System.out.println("un mot => " + line + " de taille " + tailleMot);
				
				listGutemberg.add(mot);
				if (mot.getNomMot().endsWith("ver")) {
					listFinParVer.add(mot) ;
				}
				i++;
				}

			}
			
			System.out.println("nbr de mot dans ce texte " + listGutemberg.size());

			//titre = line.substring(0, line.length());
			//System.out.println("le titre est : " + titre);

		bfr.close(); 

	} catch (MalformedURLException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}

	mapOne.put("mapdesmotc", listGutemberg);
	mapOne.put("ListeTerminésParVer", listFinParVer);
	return listGutemberg;


}

private boolean trouverTitre(String line) {
	
	if (line.contains("<h1>")) {

		System.out.println("youpi j'ai trouvé le titre : " + titre);
		return true;


	}
	else { return false;}


}


}
